package com.fatgirl.net.netConnection
{
	import com.fatgirl.net.IMessage;
	import com.fatgirl.net.IProtocol;
	import com.fatgirl.time.ITimerElement;
	import com.fatgirl.time.ITimerVisitor;
	import com.fatgirl.time.TimerFactory;
	
	import flash.events.NetStatusEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.NetConnection;
	import flash.net.Responder;
	import flash.utils.ByteArray;
	
	/**
	 *  
	 * 基于NetConnection的通讯
	 * 传输格式 统一为byteArray
	 * @author iceman
	 * 
	 */
	public class NetConnecter implements INetConnecter, ITimerElement
	{
		private var m_Protocol:IProtocol;
		private var m_NetConnection:NetConnection;
		private var m_Responder:Responder;
		private var m_bCalling:Boolean = false;
		private var m_timerVisitor:ITimerVisitor;
		private var m_callList:Vector.<Object>;
		private var m_SuccessFun:Function;
		private var m_ErrorFun:Function;
		public function NetConnecter()
		{
			m_NetConnection = new NetConnection;
			m_NetConnection.addEventListener(NetStatusEvent.NET_STATUS,netStatusHandler);
			m_NetConnection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
			m_Responder = new Responder(resultHandler,statusHandler);
			m_timerVisitor = TimerFactory.getInstance().getTimerVisitor("com.fatgirl.net.netConnection.NetConnecter");
			m_timerVisitor.addTimer(10000,this);
			
			m_callList = new Vector.<Object>;
		}
		/**
		 * 建立连接 
		 * @param _command
		 * @param args
		 * 
		 */
		public function connect(_command:String,...args):void
		{
			m_NetConnection.connect(_command,args);
		}
		/**
		 * 关闭 
		 * 
		 */
		public function close():void
		{
			m_NetConnection.close();
		}
		/**
		 * 设置超时时间 
		 * @param _delay
		 * 
		 */
		public function setOvertime(_delay:int):void
		{
			m_timerVisitor.addTimer(_delay,this);
		}
		/**
		 *  
		 * 此处发送消息为单线发送
		 * 若第一个消息没有回调消息，则其他之后请求均排队操作
		 * 直到消息超时为止 或者 请求完毕 才能进行下个请求
		 * @param _Icmd 消息对象
		 * 
		 */
		public function call(_IMessage:IMessage):void
		{
			if(m_bCalling)
			{
				m_callList.push(_IMessage);
				return; 
			}
			m_bCalling = true;
			var t_cmd:String = _IMessage.id as String;
			var t_output:ByteArray = new ByteArray;
			m_Protocol.write(t_output,_IMessage);
			m_NetConnection.call(t_cmd,m_Responder,t_output);
			//开始启动定时器
			m_timerVisitor.resetTimer(this);
			m_timerVisitor.startTimer(this);
		}
		
		/**
		 * 获取协议解析器 
		 * @return 
		 * 
		 */
		public function getProtocol():IProtocol
		{
			return m_Protocol;
		}
		
		/**
		 * 设置协议解析器 
		 * @param _IPackProto
		 * 
		 */
		public function setProtocol(_IPackProto:IProtocol):void
		{
			m_Protocol = _IPackProto;
		}
		private function goOnCall():void
		{
			if(m_callList.length>0)
			{
				call(m_callList.shift());
			}
		}
		/**
		 * 定时执行任务
		 * 丢弃无响应请求
		 * @param _timeError 传入时间误差 大于原始数返回  正数  小于则返回负数 
		 * 
		 */
		public function timeExecute(_timeError:int):void
		{
			m_bCalling = false;
			m_timerVisitor.stopTimer(this);
			goOnCall();
			
		}
		/**
		 * 请求成功 
		 * @param _obj
		 * 
		 */
		private function resultHandler(_obj:Object):void
		{
			m_timerVisitor.stopTimer(this);
			m_bCalling = false;
			var t_byte:ByteArray = _obj as ByteArray;
			m_Protocol.read(t_byte);
			goOnCall();
			
			
		}
		/**
		 * 请求出错 
		 * @param _obj
		 * 
		 */
		private function statusHandler(_obj:Object):void
		{
			m_timerVisitor.stopTimer(this);
			m_bCalling = false;
			var t_byte:ByteArray = _obj as ByteArray;
			m_Protocol.read(t_byte);
			goOnCall();
		}
		private function netStatusHandler(e:NetStatusEvent):void
		{
			switch (e.info.code) 
			{
				case "NetConnection.Connect.Success":
					if(m_SuccessFun!=null)
					{
						m_SuccessFun.apply();
					}
					break;
				default:
					if(m_ErrorFun!=null)
					{
						m_ErrorFun.apply();
					}
					break;
			}
		}
		private function securityErrorHandler(e:SecurityErrorEvent):void
		{
			m_ErrorFun.apply();
		}
		/**
		 * 设置连接成功回调
		 * @param _fun
		 * 
		 */
		public function setConnectSuccess(_fun:Function):void
		{
			m_SuccessFun = _fun;
		}
		/**
		 * 设置连接错误回调
		 * @param _fun
		 * 
		 */
		public function setConnectErrorFun(_fun:Function):void
		{
			m_ErrorFun = _fun;
		}
	}
}